﻿using AutoMapper;
using HamcoWcs.Contract.ContractCommon;
using HamcoWcs.Contract.ContractForeEnd;
using HamcoWcs.Contract.ContractMainTask;
using HamcoWcs.Contract.ContractMes;
using HamcoWcs.DAL;
using HamcoWcs.Entitys.MainTasks;
using HamcoWcs.Entitys.PalletInfos;
using HamcoWcs.Entitys.SubTasks;
using HamcoWcs.Models.Common;
using HamcoWcs.Models.Common.Enums;
using HamcoWcs.Models.Exceptions;
using HamcoWcs.Models.ForeEndModels.UITasks;
using HamcoWcs.Models.TibcoMessage.Items;
using HamcoWcs.Service.Common;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
using NPOI.SS.Formula.Functions;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using Qin.Common;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace HamcoWcs.Main.Controllers.Wcs
{    /// <summary>
     /// 主任务，子任务相关接口
     /// </summary>
    public class TaskController : BasicController
    {
        private readonly IForeEndTaskService _foreEndTaskService;
        private readonly IBaseTaskService _baseTaskService;
        private readonly IBaseMainTaskService _mainTaskService;
        private readonly IMesCommunicateService _mesCommunicateService;
        private readonly IPalletService _palletService;
        private readonly IPathService _pathService;
        private readonly ILocationService _locationService;
        private readonly AutomaticStorageInfo _asrs;

        /// <summary>
        /// 
        /// </summary>
        public override string ControllerName => "TaskController";

        /// <summary>
        /// 
        /// </summary>
        public TaskController(IBaseConfigService config, WcsDbContext wcsDbContext, IMapper mapper, ILoggerService logger, IForeEndTaskService foreEndTaskService
            , IBaseTaskService baseTaskService,
            IMesCommunicateService mesCommunicateService
            , IPalletService palletService,
            ILocationService locationService,
            IBaseMainTaskService mainTaskService,
            AutomaticStorageInfo asrs

          ) : base(logger, mapper, wcsDbContext)
        {
            _config = config;
            _foreEndTaskService = foreEndTaskService;
            _baseTaskService = baseTaskService;
            _mesCommunicateService = mesCommunicateService;
            _palletService = palletService;
            _locationService = locationService;
            _mainTaskService = mainTaskService;
            _asrs = asrs;
        }


        /// <summary>修改任务优先级</summary>
        [HttpPost]
        public IActionResult ChangeMainTaskPriority(MainTaskChangePriorityDto dto, [FromHeader] string userName)
        {
            try
            {
                string description = _baseTaskService.ChangeMainTaskPriority(dto);
                description = userName + description;
                AddOperationLog(userName, description);
                _logger.AddWcsRunLog(dto.UnitId, description);
                return Json(new ForeEndResult());
            }
            catch (Exception e)
            {
                return Json(new ForeEndResult() { Code = 0, Details = $"创建主任务失败:{e.Message}" });
            }
        }
        [HttpPost]
        public IActionResult PutTasks()
        {
            try
            {
                //任务同步
                var maintasks = _wcsDbContext.MainTasks.ToList();
                if (maintasks.Count != 0)
                    _mesCommunicateService.TransportJobListReportByWCS(maintasks);
                return Json(new ForeEndResult());
            }
            catch (Exception e)
            {
                return Json(new ForeEndResult() { Code = 0, Details = $"任务同步失败:{e.Message}" });
            }
        }

        /// <summary>
        /// 获取超时任务详情
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public IActionResult GetMainTaskTimeOut()
        {
            try
            {
                int timeout = 30;
                _config.TryGetConfigValue("TASK_TIMEOUT_THRESHOLD", out string value);
                if (!value.IsNullOrEmpty() && value != "0")
                {
                    timeout = int.Parse(value);
                }
                var mainTasks = _wcsDbContext.MainTasks.Where(x => x.CreatedTime.AddMinutes(timeout) < DateTime.Now).OrderByDescending(c => c.CreatedTime).ToList();

                var mainTaskTimeOuts = _mapper.Map<List<UIMainTaskTimeOut>>(mainTasks);
                mainTaskTimeOuts.ForEach(x =>
                {
                    if (x.StartTime == "0001/1/1 0:00:00")
                    {
                        x.StartTime = "";
                    }
                });

                return Json(new ForeEndResult(mainTaskTimeOuts));
            }
            catch (WarningException ex)
            {
                return Warning(ex);
            }
            catch (System.Exception ex)
            {
                AddSystemLog(ex.Message);
                return QueryFailureResult();
            }
        }

        /*
{
  "taskType": "InboundTask",
  "fromLoc": "CJRCV100",
  "toLoc": "CJSTW100Z4",
  "unitId": "PB0123"
}
        */


        private MachineAddressDto GetTargetAddress(string target, bool isFrom = true)
        {
            var addr = new MachineAddressDto();

            if (target.IsShelf())
            {
                var loc = _wcsDbContext.WcsLocations.FirstOrDefault(x => x.WcsLocName == target && x.LocType == "shelf");

                if (loc == null) throw new WarningException($"未找到对应货架[{target}]");
                if (loc.IsLock) throw new WarningException($"货位[{target}]已锁定，无法操作");
                if (loc.SrmOccupyFlag) throw new WarningException($"货位[{target}]堆垛机占位，无法操作");

                if (isFrom)
                {
                    if (loc.LocStatus != (int)EnumLocStatus.Store) throw new WarningException($"货位[{target}]不为存储状态，无法出库");
                    loc.LocStatus = (int)EnumLocStatus.Out;
                }
                else
                {
                    if (loc.LocStatus != (int)EnumLocStatus.Empty) throw new WarningException($"货位[{target}]不为空状态，无法入库");
                    loc.LocStatus = (int)EnumLocStatus.In;
                }
                //_wcsDbContext.SaveChanges();


                addr.MachineName = loc.ZoneName.Substring(0, loc.ZoneName.Length - 2);
                addr.PositionName = target;
                addr.ZoneName = loc.ZoneName;
                addr.PositionType = "SHELF";
            }
            else if (target.IsZone())
            {
                var loc = _locationService.GetEmptyLocation(target);
                if (loc == null) throw new Exception($"区域[{target}]未找到空货架");
                addr.MachineName = loc.ZoneName.Substring(0, loc.ZoneName.Length - 2);
                addr.PositionName = loc.WcsLocName;
                addr.ZoneName = loc.ZoneName;
                addr.PositionType = "SHELF";
            }
            else
            {
                addr.MachineName = target;
                addr.PositionName = "01";
                addr.ZoneName = "";
                addr.PositionType = "PORT";
            }


            return addr;
        }

        private EnumMainTaskType GetTaskType(string fType, string tType)
        {
            if (tType.Equals("SHELF") && fType.Equals("SHELF"))
            {
                return EnumMainTaskType.LocMoveTask;
            }
            else
            {
                if (!tType.Equals("SHELF") && !fType.Equals("SHELF"))
                {
                    return EnumMainTaskType.PortMoveTask;
                }
                else
                {
                    if (!tType.Equals("SHELF"))
                    {
                        return EnumMainTaskType.OutboundTask;
                    }
                    else
                    {
                        return EnumMainTaskType.InboundTask;
                    }
                }
            }
        }



        /// <summary>创建主任务</summary>
        [HttpPost]
        public IActionResult CreateMainTask(MainTaskCreate model, [FromHeader] string userName)
        {
            if (string.IsNullOrEmpty(model.UnitId)) return Json(ForeEndResult.Fail("传入的托盘号异常"));
            if (string.IsNullOrEmpty(model.TaskType)) return Json(ForeEndResult.Fail("传入的任务类型异常"));
            if (string.IsNullOrEmpty(model.FromLoc)) return Json(ForeEndResult.Fail("传入的起始地异常"));
            if (string.IsNullOrEmpty(model.ToLoc)) return Json(ForeEndResult.Fail("传入的目的地异常"));

            var emptyOutList = new List<string>() { "CJMCV100", "CJMCV200", "CJMCV400", "CJMCV500", "CJMCV600", "CJMCV800", "CJMCV900", "CJMCVA00" };

            try
            {
                if (!model.FromLoc.IsShelf() && !_wcsDbContext.NodeInfos.Any(x => x.NodeName == model.FromLoc))
                    throw new WarningException($"未找到起始地地{model.FromLoc}");

                if (!model.ToLoc.IsShelf() && !_wcsDbContext.NodeInfos.Any(x => x.NodeName == model.ToLoc))
                    throw new WarningException($"未找到目的地{model.ToLoc}");

                if (model.FromLoc.Contains("RGV") || model.ToLoc.Contains("RGV"))
                    throw new WarningException($"路径异常，无法创建该任务，请在正常节点创建任务");

                if (model.FromLoc.IsShelf() && model.ToLoc.Contains("RCV"))
                {
                    var n = _asrs.Nodes.FirstOrDefault(x => x.NodeName == model.ToLoc)
                        ?? throw new WarningException("未找到目的地");

                    var worktype = n.Pcons.FirstOrDefault()?.WorkType ?? throw new WarningException("未找到目的地设备");

                    if (worktype == 1) throw new WarningException($"设备{model.ToLoc}不是出库模式");
                }

                var isExistsTask = _mainTaskService.ChcekPalletTaskExists(model.UnitId);
                if (isExistsTask)
                    return Json(ForeEndResult.Fail($"已存在栈板{model.UnitId}的主任务"));
                if (emptyOutList.Contains(model.ToLoc))
                {
                   var isEmptyBox =  _wcsDbContext.Set<PalletInfo>().AsQueryable().Any(x => x.UnitId == model.UnitId && x.PalletType == "EMPTYBOX");
                   if (!isEmptyBox)
                    {
                        return Json(ForeEndResult.Fail($"{model.UnitId}不是空包，不允许搬运到空包线体"));
                    }
                   
                }
                var task = _mainTaskService.CreateTaskByWcs(model);
                AddOperationLog(userName, $"创建任务{task.TaskId}");
                _logger.AddWcsRunLog(task.UnitId, $"创建任务{task.TaskId}");
                return Json(ForeEndResult.Ok);
            }
            catch (WarningException e)
            {
                return Warning(e);
            }
            catch (Exception e)
            {
                AddSystemLog(e.Message);
                return Json(ForeEndResult.Fail("创建主任务失败"));
            }
        }


        ///// <summary>创建快速出库任务</summary>
        //[HttpPost]
        //public IActionResult CreateOutboundMainTask(OutboundCreateModel model, [FromHeader] string userName)
        //{
        //    if (string.IsNullOrEmpty(model.UnitId)) return Json(ForeEndResult.Fail("传入的托盘号异常"));
        //    if (string.IsNullOrEmpty(model.FromLoc)) return Json(ForeEndResult.Fail("传入的起始地异常"));
        //    if (string.IsNullOrEmpty(model.ToLoc)) return Json(ForeEndResult.Fail("传入的目的地异常"));

        //    try
        //    {
        //        var isExistsTask = _mainTaskService.ChcekPalletTaskExists(model.UnitId);
        //        if (isExistsTask)
        //            return Json(ForeEndResult.Fail($"已存在栈板{model.UnitId}的主任务"));

        //        var mainTaskCreate = new MainTaskCreate()
        //        {
        //            FromLoc = model.FromLoc,
        //            ToLoc = model.ToLoc,
        //            UnitId = model.UnitId,
        //            TaskType = ""
        //        };

        //        var task = _mainTaskService.CreateTaskByWcs(mainTaskCreate);
        //        AddOperationLog(userName, $"创建任务{task.TaskId}");
        //        _logger.AddWcsRunLog(task.UnitId, $"创建任务{task.TaskId}");
        //        return Json(ForeEndResult.Ok);
        //    }
        //    catch (WarningException e)
        //    {
        //        return Warning(e);
        //    }
        //    catch (Exception e)
        //    {
        //        AddSystemLog(e.Message);
        //        return Json(ForeEndResult.Fail("创建主任务失败"));
        //    }
        //}


        private bool CheckLocName(string[] toloc)
        {
            foreach (var loc in toloc)
            {
                if (!loc.IsShelf())
                {
                    return false;
                }
            }
            return true;
        }
        /// <summary>创建盘点任务</summary>
        [HttpPost]
        public IActionResult CreateInventoryTask(InventoryTaskInfo createDto, [FromHeader] string userName)
        {

            if (createDto.Mode < EnumInventoryMode.ByShelf || createDto.Mode > EnumInventoryMode.All) return Json(ForeEndResult.Fail("创建类型错误"));
            if (createDto.Mode == EnumInventoryMode.ByShelf && createDto.Shelves.Length == 0) return Json(ForeEndResult.Fail("请选择货位"));
            if (createDto.Mode == EnumInventoryMode.ByShelf && !CheckLocName(createDto.Shelves)) return Json(ForeEndResult.Fail("填入的的货架存在异常选项"));
            if (createDto.Mode == EnumInventoryMode.BySrm && string.IsNullOrEmpty(createDto.TargetSrm)) return Json(ForeEndResult.Fail("请选择堆垛机"));
            if (createDto.Mode == EnumInventoryMode.BySrm && !createDto.TargetSrm.IsSrmName()) return Json(ForeEndResult.Fail("请选择堆垛机"));



            try
            {
                var mainTaskDto = new MainTask()
                {
                    Sender = "WCS",
                    MainTaskType = EnumMainTaskType.InventoryTask.ToString(),
                    //s = "",
                    //ToLoc = "",
                    Priority = GlobalValue.DEFAULT_INVENTORY_TASK_PRIORITY,
                    UnitId = "",
                    TaskId = $"{DateTime.Now:yyyyMMddHHmmss}-Inventory-WCS",
                    TaskStatus = EnumMainTaskStatus.NewTask.ToString(),
                    InventoryInfo = JsonConvert.SerializeObject(createDto)
                    //Extend = new ExtendDto()
                    //{
                    //    IsReportStart = false,
                    //    InventoryTaskInfo = createDto
                    //}
                };

                //var mainTask = _mapper.Map<MainTask>(mainTaskDto);

                _wcsDbContext.MainTasks.Add(mainTaskDto);
                _wcsDbContext.SaveChanges();

                return Json(ForeEndResult.Ok);
            }
            catch (WarningException e)
            {
                return Warning(e);
            }
            catch (Exception e)
            {
                AddSystemLog(e.Message);
                return Json(ForeEndResult.Fail("创建盘点主任务失败"));
            }
        }


        /// <summary>
        /// 暂停主任务
        /// </summary>
        /// <param name="model"></param>
        /// <param name="userName"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult PauseMainTask(BaseModel model, [FromHeader] string userName)
        {


            try
            {
                var mainTask = _wcsDbContext.MainTasks.FirstOrDefault(x => x.Id == model.Id)
                    ?? throw new WarningException("找不到主任务");
                if (mainTask.TaskStatus == EnumMainTaskStatus.Error.ToString())
                    throw new WarningException("主任务异常");
                if (!(mainTask.TaskStatus == EnumMainTaskStatus.OnProgress.ToString()
                    || mainTask.TaskStatus != EnumMainTaskStatus.Ready.ToString()))
                    //|| mainTask.TaskStatus != EnumMainTaskStatus.Ready.ToString()
                    throw new WarningException("主任务无法暂停");


                mainTask.ReasonCode = mainTask.TaskStatus;
                mainTask.TaskStatus = EnumMainTaskStatus.Pause.ToString();
                _wcsDbContext.SaveChanges();
                AddOperationLog(userName, $"暂停主任务{mainTask.TaskId}", mainTask.UnitId, mainTask.CurrentMachine);
                //_mesCommunicateService.PalletTransportJobTerminatedByAGV(mainTask);
                return Json(new ForeEndResult());
            }
            catch (WarningException ex)
            {
                return Warning(ex);
            }
            catch (Exception e)
            {
                AddSystemLog(e.Message);
                return DeleteFailureResult();
            }
        }

        /// <summary>
        /// 开始暂停的主任务
        /// </summary>
        [HttpPost]
        public IActionResult StartMainTask(BaseModel model, [FromHeader] string userName)
        {
            try
            {
                var mainTask = _wcsDbContext.MainTasks.FirstOrDefault(x => x.Id == model.Id)
                    ?? throw new WarningException("找不到主任务");
                if (mainTask.TaskStatus == EnumMainTaskStatus.Error.ToString())
                    throw new WarningException("主任务异常");
                if (mainTask.TaskStatus != EnumMainTaskStatus.Pause.ToString())
                    throw new WarningException("主任务未暂停");


                mainTask.TaskStatus = mainTask.ReasonCode;
                _wcsDbContext.SaveChanges();
                AddOperationLog(userName, $"开始暂停的主任务{mainTask.TaskId}", mainTask.UnitId, mainTask.CurrentMachine);
                return Json(new ForeEndResult());
            }
            catch (WarningException ex)
            {
                return Warning(ex);
            }
            catch (Exception e)
            {
                AddSystemLog(e.Message);
                return DeleteFailureResult();
            }
        }

        /// <summary>删除主任务</summary>
        [HttpPost]
        public IActionResult DeleteMainTask(List<long> ids, [FromHeader] string userName)
        {
            try
            {
                var mainTasks = _wcsDbContext.MainTasks.Where(x => ids.Contains(x.Id)).ToList();

                var errs = new List<string>();
                foreach (var mainTask in mainTasks)
                {
                    try
                    {
                        //if (mainTask.TaskStatus == EnumMainTaskStatus.Error.ToString())
                        //    throw new WarningException("主任务异常");
                        if (mainTask.TaskStatus == EnumMainTaskStatus.OnProgress.ToString())
                            throw new WarningException("主任务已开始");
                        mainTask.TaskStatus = EnumMainTaskStatus.Cancel.ToString();
                    }
                    catch (WarningException ex)
                    {
                        errs.Add($"{mainTask.TaskId}删除失败");
                        _logger.AddWcsRunLog(mainTask.UnitId, $"主任务删除失败：{ex.Message}");
                        continue;
                    }

                    AddOperationLog(userName, $"{userName}取消主任务{mainTask.TaskId}", mainTask.UnitId, mainTask.CurrentMachine);
                }

                _wcsDbContext.SaveChanges();

                if (errs.Count == 0)
                {
                    return Json(ForeEndResult.Ok);

                }
                else
                {
                    return Json(ForeEndResult.Fail(string.Join('\n', errs)));
                }
            }
            catch (WarningException ex)
            {
                return Warning(ex);
            }
            catch (Exception e)
            {
                AddSystemLog(e.Message);
                return DeleteFailureResult();
            }
        }

        /// <summary>查询历史任务</summary>
        [HttpPost]
        public IActionResult QueryHistoryMainTask(QueryMainTaskHistoryModel model)
        {
            try
            {
                var result = _foreEndTaskService.QueryHistoryMainTask(model);
                return Json(result);
            }
            catch (Exception e)
            {
                return Json(new ForeEndResult() { Code = 0, Details = $"查询历史任务失败:{e.Message}" });
            }
        }

        protected static string FILE_CONTENT_TYPE = "application/octet-stream";

        /// <summary>导出主任务历史</summary>
        [HttpPost]
        public IActionResult ExportHistoryMainTask(QueryMainTaskHistoryModel model)
        {
            try
            {
                var result = _foreEndTaskService.QueryHistoryMainTask(model);
                var data = (List<UIMainTask>)result.Data;
                var wb = new XSSFWorkbook();

                ISheet st = ExcelHelper.SetSheet(wb, data);

                var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"{DateTime.Now:yyyyMMddHHmmss}historytask.xlsx");
                using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite))
                {
                    wb.Write(fs);
                }
                var nfs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Read);
                return File(nfs, FILE_CONTENT_TYPE, "export_maintask_history.xlsx");
                //return Json(ForeEndResult.Fail("Not im"));
            }
            catch (Exception e)
            {
                return Json(new ForeEndResult() { Code = 0, Details = $"查询主任务失败:{e.Message}" });
            }
        }

        /// <summary>查询子任务按主任务Id</summary>
        [HttpPost]
        public IActionResult QuerySubTaskById(BaseModel model)
        {
            try
            {
                var result = _foreEndTaskService.QuerySubTaskById(model);
                return Json(result);
            }
            catch (Exception e)
            {
                return Json(new ForeEndResult() { Code = 0, Details = $"查询子任务失败:{e.Message}" });
            }
        }

        /// <summary>查询主任务</summary>
        [HttpPost]
        public IActionResult QueryMainTask(QueryMainTask queryMainTask)
        {
            try
            {
                var result = _foreEndTaskService.QueryMainTask(queryMainTask);
                return Json(result);
            }
            catch (Exception e)
            {
                return Json(new ForeEndResult() { Code = 0, Details = $"查询主任务失败:{e.Message}" });
            }
        }


        /// <summary>查询子任务</summary>
        [HttpPost]
        public IActionResult QuerySubTask(QuerySubTask querySubTask, [FromHeader] string userName)
        {
            try
            {
                var result = _foreEndTaskService.QuerySubTask(querySubTask);
                return Json(result);
            }
            catch (Exception e)
            {
                return Json(new ForeEndResult() { Code = 0, Details = $"查询子任务失败:{e.Message}" });
            }
        }

        /// <summary>更新子任务</summary>
        [HttpPost]
        public IActionResult UpdateSubTask(UIUpdateSubtask uIUpdateSubtask, [FromHeader] string userName)
        {
            try
            {
                var subtask = _wcsDbContext.SubTasks.AsNoTracking().FirstOrDefault(x => x.Id == uIUpdateSubtask.taskId);
                //if (subtask.TaskStatus != EnumSubTaskStatus.OnProgress.ToString())
                //    throw new Exception("子任务状态异常");
                var result = _baseTaskService.UpdateSubTaskStatus(uIUpdateSubtask.taskId, uIUpdateSubtask.TaskStatus);
                AddOperationLog(userName, $"更新{uIUpdateSubtask.unitId}子任务状态:{uIUpdateSubtask.TaskStatus}");
                return Json(new UpdateSubTaskResult() { IsUpdate = result });

            }
            catch (Exception e)
            {
                return Json(new UpdateSubTaskResult() { Code = 0, Details = $"更新子任务状态失败:{e.Message}" });
            }

        }


        /// <summary>获取堆垛机正在执行的任务</summary>
        [HttpPost]
        public IActionResult QueryCurrentSrmTask(SrmTaskQueryModel model)
        {
            try
            {
                var srm = _asrs.Srms.FirstOrDefault(x => x.SrmName == model.SrmName)
                    ?? throw new WarningException($"未找到堆垛机{model.SrmName}");

                var _gain = GetDiatanceGain();

                var onprogressTask = _wcsDbContext.SubTasks
                     .AsNoTracking()
                     .Where(x => x.PlcName == srm.SrmName)
                     .Where(x => x.TaskStatus == EnumSubTaskStatus.OnProgress.ToString())
                     .Include(x => x.MainTask)
                     .FirstOrDefault();

                var subtasks = new List<SubTask>();
                if (onprogressTask != null)
                {
                    subtasks.Add(onprogressTask);
                }


                // 获取该堆垛机的所有任务
                var mainTasks = _wcsDbContext.MainTasks
                    .AsNoTracking()
                    .Where(x => x.TaskStatus == EnumMainTaskStatus.OnProgress.ToString()
                             || x.TaskStatus == EnumMainTaskStatus.Ready.ToString())
                    .Include(x => x.SubTasks)
                    .Where(x => x.SubTasks.Any(s => s.PlcName == model.SrmName
                                                 && (s.TaskStatus == EnumSubTaskStatus.Ready.ToString())))
                    .ToList();

                if (mainTasks.Count > 0)
                {
                    foreach (var task in mainTasks)
                    {
                        var priority = 0;
                        try
                        {
                            priority = int.Parse(task.Priority);
                        }
                        catch (System.Exception)
                        {
                            priority = 60;
                        }

                        var fp = task.SrcPriority;
                        var tp = task.DesPriority;


                        var subtask = task.SubTasks.FirstOrDefault(x => x.TaskStatus == EnumSubTaskStatus.Ready.ToString());

                        var sBay = GetSourceBay(subtask.FromLoc, srm.Aisle.NodeName);
                        var distance = Math.Abs(srm.CurrentBay - sBay);

                        if (distance > 7)
                        {
                            task.ComplexPriority = priority + fp + tp;
                        }
                        else
                        {
                            task.ComplexPriority = priority + fp + tp + (10 - distance) * _gain;
                        }
                    }




                    foreach (var task in mainTasks.OrderByDescending(x => x.ComplexPriority))
                    {
                        var subtask = task.SubTasks.FirstOrDefault(x => x.TaskStatus == EnumSubTaskStatus.Ready.ToString());
                        subtasks.Add(subtask);
                    }
                }

                var data = _mapper.Map<List<UISrmSubTask>>(subtasks);

                return Json(new ForeEndResult(data));
            }
            catch (Exception ex)
            {
                AddSystemLog(ex.Message);
                return QueryFailureResult();
            }

        }


        private int GetDiatanceGain()
        {
            var _gain = 3;
            var a = _config.TryGetConfigValue("DISTANCEGAIN", out string g);

            try
            {
                if (a)
                {
                    _gain = int.Parse(g);
                }
            }
            catch (Exception)
            {
                _gain = 3;
            }

            return _gain;
        }
        private int GetSourceBay(string fLoc, string aisleName)
        {
            if (fLoc.IsShelf())
            {
                var b = fLoc.Substring(2, 3);
                try
                {
                    return int.Parse(b);
                }
                catch (Exception)
                {
                    return 0;
                }
            }
            else
            {
                if (fLoc == "CJRCV100") return 5;
                if (fLoc == "CJRCV200") return 7;
                if (fLoc == "CJRCV300") return 6;
                if (fLoc == "CJRCV400") return 8;

                if (fLoc == "CJVCV100" && aisleName == "CJSTW100") return 6;
                if (fLoc == "CJVCV100" && aisleName == "CJSTW200") return 15;
                if (fLoc == "CJVCV200" && aisleName == "CJSTW100") return 28;
                if (fLoc == "CJVCV200" && aisleName == "CJSTW200") return 37;

                if (fLoc == "CJVCV300") return 55;
                if (fLoc == "CJVCV400") return 57;

                if (fLoc == "CJVCV700") return 26;
                if (fLoc == "CJVCV800") return 28;
            }
            return 0;
        }



        /// <summary>获取堆垛机正在执行的任务数量</summary>
        [HttpPost]
        public IActionResult QueryCurrentSrmTaskCount()
        {
            try
            {
                var dic = new Dictionary<string, int>();
                for (int i = 1; i <= 4; i++)
                {
                    var srmName = $"Srm0{i}";

                    var count = _wcsDbContext.SubTasks
                    .AsNoTracking()
                    .Where(x => x.PlcName == srmName)
                    .Where(x => x.TaskStatus == EnumSubTaskStatus.OnProgress.ToString()
                             || x.TaskStatus == EnumSubTaskStatus.Ready.ToString())
                    .Include(x => x.MainTask)
                    .Where(x => x.MainTask.TaskStatus == EnumMainTaskStatus.OnProgress.ToString()
                             || x.MainTask.TaskStatus == EnumMainTaskStatus.Ready.ToString())
                    .Count();

                    dic.Add(srmName, count);
                }
                return Json(new ForeEndResult(dic));
            }
            catch (Exception ex)
            {
                AddSystemLog(ex.Message);
                return QueryFailureResult();
            }

        }


        /// <summary>变更目的地</summary>
        [HttpPost]
        public IActionResult ChangePPKTaskDestination(ChangePPKTaskModel model, [FromHeader] string userName = "")
        {
            try
            {
                if (string.IsNullOrEmpty(model.NewDesMachine)) throw new WarningException("新目的地不得为空");

                var mainTask = _wcsDbContext.MainTasks.FirstOrDefault(x => x.TaskId == model.TaskId)
                ?? throw new WarningException($"未找到任务号为{model.TaskId}的任务");

                var oldLoc = mainTask.DesMachine;
                var newLoc = model.NewDesMachine;


                if (!PPKMACHINENAMES.Contains(oldLoc)) throw new WarningException("非法的旧目的地");
                if (!PPKMACHINENAMES.Contains(newLoc)) throw new WarningException("非法的新目的地");
                //|| !PPKMACHINENAMES.Contains(newLoc)) throw new WarningException("非法的目的地");
                if (oldLoc == newLoc) throw new WarningException("相同的目的地");

                switch (Enum.Parse<EnumMainTaskStatus>(mainTask.TaskStatus))
                {
                    case EnumMainTaskStatus.NewTask:
                    case EnumMainTaskStatus.Ready:
                    case EnumMainTaskStatus.OnProgress:
                        mainTask.OldDesMachine = mainTask.DesMachine;
                        mainTask.OldDesPosition = mainTask.DesPosition;
                        mainTask.OldDesType = mainTask.DesType;
                        mainTask.OldDesZone = mainTask.DesZone;

                        mainTask.DesMachine = newLoc;
                        //mainTask.DesPosition = jobMessage.Body.NewDestinationPositionName;
                        //mainTask.DesType = jobMessage.Body.NewDestinationPositionType;
                        //mainTask.DesZone = "";

                        if (mainTask.TaskStatus == EnumMainTaskStatus.NewTask.ToString()
                         || mainTask.TaskStatus == EnumMainTaskStatus.Ready.ToString())
                        {
                            mainTask.SubTasks.Clear();
                            mainTask.TaskStatus = EnumMainTaskStatus.NewTask.ToString();
                        }
                        else
                        {
                            if (mainTask.TotalSubTaskNum - mainTask.ActiveSubTaskId >= 2)
                            {
                                var stask = mainTask.SubTasks.FirstOrDefault(x => x.ToLoc == oldLoc)
                                    ?? throw new WarningException($"Not found the subTask that destination machine is '{oldLoc}'");
                                stask.ToLoc = newLoc;
                            }
                            else
                            {
                                throw new WarningException("该任务已经无法修改目的地");
                            }
                        }

                        _logger.AddWcsRunLog(mainTask.UnitId, $"WCS变更目的地{oldLoc}->{newLoc}，TaskId:{mainTask.TaskId}");
                        break;
                    case EnumMainTaskStatus.Finished:
                    case EnumMainTaskStatus.Error:
                    case EnumMainTaskStatus.Delete:
                    case EnumMainTaskStatus.Cancel:
                    default:
                        throw new WarningException($"拒绝切换目的地:'{mainTask.TaskStatus}'");
                }

                _wcsDbContext.SaveChanges();
                return Json(ForeEndResult.Ok);
            }
            catch (WarningException ex)
            {
                return Warning(ex);
            }
            catch (Exception ex)
            {
                AddSystemLog(ex.Message);
                return UnknownExceptionResult();
            }

        }

        /// <summary>查询货位指定类型栈板</summary>
        [HttpPost]
        public IActionResult QueryTargetPallet(QueryTargetPalletModel model)
        {
            try
            {
                if (string.IsNullOrEmpty(model.Size)) throw new WarningException("请输入尺寸");

                var locs = _wcsDbContext.WcsLocations
                     .AsNoTracking()
                     .Where(x => !x.IsLock && !x.SrmOccupyFlag)
                     .Where(x => x.LocStatus == 1)
                     .Where(x => !string.IsNullOrEmpty(x.UnitId))
                     .ToList();

                var pallets = _wcsDbContext.Set<PalletInfo>()
                    .AsNoTracking()
                    .Where(x => x.Size == model.Size)
                    .Where(x => x.PalletType == model.Type)
                    .Select(x => x.UnitId)
                    .ToList();


                var loc = locs.FirstOrDefault(x => pallets.Contains(x.UnitId));
                if (loc == null) throw new WarningException("未找到对应尺寸的可用栈板");
                return Json(new ForeEndResult(loc));
            }
            catch (WarningException e)
            {
                return Warning(e);
            }
            catch (Exception e)
            {
                return Json(new ForeEndResult() { Code = 0, Details = $"查询主任务失败:{e.Message}" });
            }
        }


        /// <summary>更改BUFFER位的目的地</summary>
        [HttpPost]
        public IActionResult ChangeBufferDestination(ChangeBufferDestinationModel model, [FromHeader] string userName = "UNK")
        {
            try
            {
                if (string.IsNullOrEmpty(model.NewDestination)) throw new WarningException("请输入新目的地");
                if (string.IsNullOrEmpty(model.MachineName)) throw new WarningException("请输入机台名");
                if (string.IsNullOrEmpty(model.PortName)) throw new WarningException("请输入Port名");
                if (string.IsNullOrEmpty(model.UnitId)) throw new WarningException("请输入栈板号");

                if (!model.MachineName.Contains("CJBUF"))
                    throw new WarningException("请输入Buffer的机台名");

                var pcon = _asrs.Pcons.FirstOrDefault(x => x.MachineName.Equals(model.MachineName) && x.PortName.Equals(model.PortName))
                    ?? throw new WarningException("未找到对应设备");

                if (!PPKMACHINENAMES.Contains(model.NewDestination))
                    throw new WarningException("请输入正确的目的地");

                // 设备占位中
                if (pcon.PconMode != 7)
                    throw new WarningException("设备非占位中无法修改目的地");

                var task = _wcsDbContext.MainTasks.Include(x => x.SubTasks)
                    .FirstOrDefault(x => x.UnitId == model.UnitId)
                    ?? throw new WarningException("未找到对应栈板的任务设备");

                if (task.DesMachine == model.NewDestination)
                    throw new WarningException("新目的地和原任务的相同");

                var subTask = task.SubTasks.Last();

                subTask.TaskStatus = EnumSubTaskStatus.Change.ToString();
                var newSubTask = new SubTask()
                {
                    TaskSeq = subTask.TaskSeq + 1,
                    FromLoc = pcon.MachineName,
                    ToLoc = model.NewDestination,
                    PlcName = subTask.PlcName,
                    TaskStatus = EnumSubTaskStatus.Ready.ToString(),
                    UnitId = model.UnitId,
                    TaskFrom = "WCS",
                    SubTaskType = EnumSubTaskType.PconTask.ToString(),
                };
                task.SubTasks.Add(newSubTask);

                task.ActiveSubTaskId = newSubTask.TaskSeq;
                task.TotalSubTaskNum = task.SubTasks.Count;

                task.OldDesMachine = subTask.ToLoc;
                task.OldDesPosition = "01";

                _wcsDbContext.SaveChanges();
                AddOperationLog(userName, $"{userName}修改{task.TaskId}目的地为{model.NewDestination}", model.UnitId, pcon.MachineName);
                return Json(new ForeEndResult(null));
            }
            catch (WarningException e)
            {
                return Warning(e);
            }
            catch (Exception e)
            {
                AddSystemLog(e.Message);
                return UnknownExceptionResult();
            }
        }

        /// <summary>更改提升机的目的地</summary>
        [HttpPost]
        public IActionResult ChangeMIFDestination(ChangeBufferDestinationModel model, [FromHeader] string userName = "UNK")
        {
            try
            {
                if (string.IsNullOrEmpty(model.NewDestination)) throw new WarningException("请输入新目的地");
                if (string.IsNullOrEmpty(model.MachineName)) throw new WarningException("请输入机台名");
                if (string.IsNullOrEmpty(model.PortName)) throw new WarningException("请输入Port名");
                if (string.IsNullOrEmpty(model.UnitId)) throw new WarningException("请输入栈板号");

                if (!model.MachineName.Contains("CJBUF"))
                    throw new WarningException("请输入Buffer的机台名");

                var pcon = _asrs.Pcons.FirstOrDefault(x => x.MachineName.Equals(model.MachineName) && x.PortName.Equals(model.PortName))
                    ?? throw new WarningException("未找到对应设备");

                if (!PPKMACHINENAMES.Contains(model.NewDestination))
                    throw new WarningException("请输入正确的目的地");

                // 设备占位中
                if (pcon.PconMode != 7)
                    throw new WarningException("设备非占位中无法修改目的地");

                var task = _wcsDbContext.MainTasks.Include(x => x.SubTasks)
                    .FirstOrDefault(x => x.UnitId == model.UnitId)
                    ?? throw new WarningException("未找到对应栈板的任务设备");

                if (task.DesMachine == model.NewDestination)
                    throw new WarningException("新目的地和原任务的相同");

                var subTask = task.SubTasks.Last();

                subTask.TaskStatus = EnumSubTaskStatus.Change.ToString();
                var newSubTask = new SubTask()
                {
                    TaskSeq = subTask.TaskSeq + 1,
                    FromLoc = pcon.MachineName,
                    ToLoc = model.NewDestination,
                    PlcName = subTask.PlcName,
                    TaskStatus = EnumSubTaskStatus.Ready.ToString(),
                    UnitId = model.UnitId,
                    TaskFrom = "WCS",
                    SubTaskType = EnumSubTaskType.PconTask.ToString(),
                };
                task.SubTasks.Add(newSubTask);

                task.ActiveSubTaskId = newSubTask.TaskSeq;
                task.TotalSubTaskNum = task.SubTasks.Count;

                task.OldDesMachine = subTask.ToLoc;
                task.OldDesPosition = "01";

                _wcsDbContext.SaveChanges();
                AddOperationLog(userName, $"{userName}修改{task.TaskId}目的地为{model.NewDestination}", model.UnitId, pcon.MachineName);
                return Json(new ForeEndResult(null));
            }
            catch (WarningException e)
            {
                return Warning(e);
            }
            catch (Exception e)
            {
                AddSystemLog(e.Message);
                return UnknownExceptionResult();
            }
        }


        /// <summary> 堆垛机周回测试 </summary>
        [HttpPost]
        public IActionResult CycleSrmTask(SrmCycleTaskModel model, [FromHeader] string userName = "UNK")
        {
            try
            {
                if (string.IsNullOrEmpty(model.UnitId)) throw new WarningException("请选择栈板号");
                if (string.IsNullOrEmpty(model.SrcLoc)) throw new WarningException("未选择起始地");
                if (string.IsNullOrEmpty(model.DesLoc)) throw new WarningException("未选择目的地");
                if (!model.SrcLoc.IsShelf()) throw new WarningException("输入起始地格式错误");
                if (!model.DesLoc.IsShelf()) throw new WarningException("输入目的地格式错误");


                if (!GlobalValue.WCSConnectState) throw new WarningException("WCS状态为在线，无法进行周回测试");

                var loc = _wcsDbContext.WcsLocations.FirstOrDefault(x => x.UnitId == model.UnitId)
                ?? throw new WarningException($"在货位中未找到栈板[{model.UnitId}]");

                if (loc.WcsLocName != model.SrcLoc) throw new WarningException($"当前栈板位置与输入的位置不同");
                if (loc.IsLock || loc.SrmOccupyFlag) throw new WarningException($"当前储位已锁定");

                var desLoc = _wcsDbContext.WcsLocations.FirstOrDefault(x => x.WcsLocName == model.DesLoc)
                ?? throw new WarningException($"未找到货位{model.DesLoc}");

                if (desLoc.IsLock || desLoc.SrmOccupyFlag) throw new WarningException($"目的储位已锁定");
                if (desLoc.LocStatus != (int)EnumLocStatus.Empty) throw new WarningException($"目的储位状态不为空");
                if (loc.Aisle != desLoc.Aisle) throw new WarningException("选择的货位不在相同巷道");

                var mainTask = new MainTask
                {
                    TaskId = $"{DateTime.Now:yyyyMMddHHmmss}-{model.UnitId}-Cycle",
                    MainTaskType = nameof(EnumMainTaskType.SrmCycleTask),
                    UnitId = model.UnitId,
                    Priority = "30",
                    TotalSubTaskNum = 1,
                    ActiveSubTaskId = 1,
                    Sender = "WCS",
                    TaskStatus = nameof(EnumMainTaskStatus.Ready),
                    SrcMachine = loc.Aisle,
                    SrcPosition = loc.WcsLocName,
                    SrcType = "SHELF",
                    SrcZone = loc.ZoneName,
                    DesMachine = desLoc.Aisle,
                    DesPosition = desLoc.WcsLocName,
                    DesType = "SHELF",
                    DesZone = desLoc.ZoneName
                };

                loc.LocStatus = (int)EnumLocStatus.Out;
                desLoc.LocStatus = (int)EnumLocStatus.In;

                mainTask.SubTasks = new List<SubTask>()
                {
                    new()
                    {
                        TaskSeq = 1,
                        UnitId = model.UnitId,
                        FromLoc = loc.WcsLocName,
                        ToLoc = desLoc.WcsLocName,
                        PlcName = loc.Aisle,
                        SubTaskType = nameof(EnumSubTaskType.SrmMoveTask),
                        TaskStatus = nameof(EnumSubTaskStatus.Ready),
                        TaskFrom = mainTask.Sender,
                    }
                };

                _wcsDbContext.MainTasks.Add(mainTask);
                _wcsDbContext.SaveChanges();
                AddOperationLog(userName, "创建了周回测试");

                return Json(ForeEndResult.Ok);
            }
            catch (WarningException ex)
            {
                return Warning(ex);
            }
            catch (Exception ex)
            {
                AddSystemLog(ex.Message);
                return QueryFailureResult();
            }

        }

        private readonly IBaseConfigService _config;
        private static List<string> PPKMACHINENAMES = new List<string>()
        {
            "CJMCV100",
            "CJMCV200",
            "CJMCV800",
            "CJMCV900",
            "CJMCVA00",
        };
    }

}


